"use client";
import React, { ReactNode, useEffect, useState, useRef } from "react";
import { useNode, useEditor, Element } from "@craftjs/core";
import { throttle } from "throttle-debounce";
import { ROOT_NODE } from "@craftjs/utils";
import cx from "classnames";
import { Img } from "./Img";
interface ImageBoxType {
	src?: string;
	width?: number;
	height?: number;
	children?: ReactNode;
}
// 核心逻辑组件
export const ImgContain = ({ children }: ImageBoxType) => {
	const {
		id,
		connectors: { connect, drag },
	} = useNode();
	const { enabled, query, actions } = useEditor((state) => ({
		// 用于代码优化，不可编辑时不进行事件注册
		enabled: state.options.enabled,
	}));
	// 用于注册事件的DOM
	const divRef = useRef(null);
	// 用于判断当前拖拽Node是否可以进入
	const [canAcceptNode, setCanAcceptNode] = useState(false);

	useEffect(() => {
		// 拖拽悬停事件，由于此事件触发太频繁，所以采取节流
		const dragover = throttle(
			100,
			(e) => {
				e.preventDefault();
				// 获取根节点
				const nodeData = query.node(ROOT_NODE).get();
				// 判断当前拖拽的组件是不是Img
				if (nodeData?.data?.custom?.DraggerEl == "Img") {
					setCanAcceptNode(true);
				} else {
					setCanAcceptNode(false);
				}
			},
			{ noLeading: false, noTrailing: true }
		);
		// 拖放事件
		const drop = (e) => {
			e.preventDefault();
			// 获取根节点
			const nodeData = query.node(ROOT_NODE).get();
			// 判断当前拖拽的组件是不是Img
			if (nodeData?.data?.custom?.DraggerEl == "Img") {
				// 获取当前节点的子节点
				const nodes = query.node(id).childNodes();
				// 删除当前节点的子节点
				actions.delete(nodes);
			}
			setCanAcceptNode(false);
		};
		// 拖放离开和结束处理
		const dragleave = (e) => {
			e.preventDefault();
			setCanAcceptNode(false);
		};
		// Dom存在并且是编辑状态注册事件
		if (divRef.current && enabled) {
			divRef.current.addEventListener("dragover", dragover);
			divRef.current.addEventListener("drop", drop);
			divRef.current.addEventListener("dragleave", dragleave);
		}
		// 使用document监听拖拽结束
		document.addEventListener("dragend", dragleave);
		return () => {
			// 移除事件，优化性能和防止出现其他问题
			if (divRef.current && enabled) {
				divRef.current.removeEventListener("dragover", dragover);
				divRef.current.removeEventListener("drop", drop);
				divRef.current.removeEventListener("dragleave", dragleave);
			}
			document.removeEventListener("dragend", dragleave);
		};
	}, [divRef, enabled]);
	return (
		<div
			ref={(ref) => {
				connect(drag(ref));
				divRef.current = ref;
			}}
			style={{
				display: "inline-block",
				border: "1px dashed #ccc",
				position: "relative",
			}}
			className={cx({
				can_accept_node: canAcceptNode,
			})}
		>
			{children}
			<style jsx>{`
				.can_accept_node {
					opacity: 0.4;
					border: 1px solid green !important;
				}
			`}</style>
		</div>
	);
};
// 组件配置对象
ImgContain.craft = {
	displayName: "ImgContain",
	rules: {
		// 只有Img组件才可以进入
		canMoveIn: (incomingNodes) => {
			return incomingNodes.every(
				(incomingNode) => incomingNode.data.type === Img
			);
		},
		// 不支持移出
		canMoveOut: () => false,
		// 只有Img组件才可以放入
		canDrop: (incomingNode) => {
			return incomingNode.data.type === Img;
		},
	},
};
/**
 * 图片盒子组件
 * @param width 宽
 * @param height 高
 * @param src 图片地址
 * @returns
 */
export const ImageBox = ({ width, height, src }: ImageBoxType) => {
	const {
		connectors: { connect, drag },
	} = useNode((state) => ({
		isActive: state.events.selected,
	}));
	return (
		<div
			ref={(ref) => {
				connect(drag(ref as HTMLElement));
			}}
			style={{ display: "inline-block" }}
		>
			<Element id="image" is={ImgContain} canvas>
				<Img width={width} height={height} src={src} />
			</Element>
		</div>
	);
};
// 默认值
const ImageBoxDefaultProps = {
	src: "https://mui.com/static/material-ui/react-components/autocomplete-light.png",
	width: 200,
	height: 100,
};
// 组件配置对象
ImageBox.craft = {
	displayName: "ImageBox",
	props: ImageBoxDefaultProps,
	rules: {
		canDrag: () => true,
	},
};
